package com.orange.cloud.common.advice;


import com.orange.cloud.common.exception.ServiceException;
import com.orange.cloud.common.msg.Message;
import com.orange.cloud.common.msg.R;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.util.NestedServletException;

import javax.validation.ConstraintViolationException;
import java.util.List;

/**
 * @program: wsw-cloud-servce
 * @description: 全局异常处理器
 * @author: wsw
 * @create: 2020-05-06 20:09
 **/
@Slf4j
@RestControllerAdvice
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class BaseExceptionHandler {

    /**
     * 全局
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public Message exceptionHandle(Exception e) {
        log.error("系统异常{}", e);
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
    }

    @ExceptionHandler(value = NullPointerException.class)
    public Message exceptionHandle(NullPointerException e) {
        log.error("系统异常{}", e);
        return R.error(HttpStatus.NOT_FOUND.value(), "资源不存在");
    }

    @ExceptionHandler(ServiceException.class)
    public Message exceptionHandle(ServiceException e) {
        log.error("业务异常{}", e);
        return R.error(e.getCode(), e.getMessage());
    }

    @ExceptionHandler(NestedServletException.class)
    public Message exceptionHandle(NestedServletException e) {
        log.error("服务异常{}", e);
        Throwable cause = e.getCause().getCause();
        if (cause instanceof ServiceException) {
            ServiceException exception = (ServiceException) cause;
            return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), exception.getMessage());
        }
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
    }

    @ExceptionHandler(Throwable.class)
    public Message exceptionHandle(Throwable e) {
        log.error("服务异常{}", e);
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
    }

    @ExceptionHandler(IllegalArgumentException.class)
    public Message exceptionHandle(IllegalArgumentException e) {
        log.error("参数异常{}", e);
        return R.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());

    }

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Message exceptionHandle(MissingServletRequestParameterException e) {
        log.error("参数异常{}", e);
        return R.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public Message exceptionHandle(MethodArgumentTypeMismatchException e) {
        log.error("参数异常{}", e);
        return R.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public Message exceptionHandle(ConstraintViolationException e) {
        log.error("参数异常{}", e);
        return R.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }


    @ExceptionHandler(NoHandlerFoundException.class)
    public Message exceptionHandle(NoHandlerFoundException e) {
        log.error("系统异常{}", e);
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public Message exceptionHandle(HttpMessageNotReadableException e) {
        log.error("系统异常{}", e);
        return R.error(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage());
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Message exceptionHandle(HttpRequestMethodNotSupportedException e) {
        log.error("系统异常{}", e);
        return R.error(HttpStatus.METHOD_NOT_ALLOWED.value(), e.getMessage());
    }

    @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
    public Message exceptionHandle(HttpMediaTypeNotSupportedException e) {
        log.error("系统异常{}", e);
        return R.error(HttpStatus.UNSUPPORTED_MEDIA_TYPE.value(), e.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})
    public Message exceptionHandle(MethodArgumentNotValidException e) {
        //打印校验住的所有的错误信息
        StringBuilder sb = new StringBuilder("参数错误:");
        BindingResult result = e.getBindingResult();
        if (result.hasErrors()) {
            List<FieldError> fieldErrors = result.getFieldErrors();
            fieldErrors.forEach(error -> sb.append("[").append(error.getField()).append(":").append(error.getDefaultMessage()).append("],"));
        }
        sb.deleteCharAt(sb.length() - 1);
        log.error(sb.toString());
        return R.error(HttpStatus.BAD_REQUEST.value(), sb.toString());
    }


}
